/**
 * 
 */
package ro.dandanciu.webgallery.sync.server.fs.services.impl;

import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.activation.MimetypesFileTypeMap;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import ro.dandanciu.webgallery.domainmodel.Gallery;
import ro.dandanciu.webgallery.domainmodel.Image;
import ro.dandanciu.webgallery.services.GalleryServices;
import ro.dandanciu.webgallery.services.ImageServices;
import ro.dandanciu.webgallery.sync.gallery.dto.GallerySyncDTO;
import ro.dandanciu.webgallery.sync.server.fs.services.FsSync;

/**
 * @author Dan Danciu
 * 
 */
@Transactional
public class FsSyncImpl implements FsSync {
    /**
     * Logger for this class
     */
    private static final Logger logger = Logger.getLogger(FsSyncImpl.class);

    private EntityManager em;
    private ImageServices imageServices;
    private GalleryServices galleryServices;

    @PersistenceContext
    public final void setEntityManager(final EntityManager em) {
        this.em = em;
    }

    /**
     * @param imageServices the imageServices to set
     */
    public final void setImageServices(final ImageServices imageServices) {
        this.imageServices = imageServices;
    }

    
    /**
     * @param galleryServices the galleryServices to set
     */
    public final void setGalleryServices(final GalleryServices galleryServices) {
        this.galleryServices = galleryServices;
    }

    public Set<GallerySyncDTO> preSynchronizeDifference(long galleryId) {
        if (logger.isDebugEnabled()) {
            logger.debug("synchronize(long) - start");
            logger.debug("galleryId:long = " + galleryId);
        }

        // get local images, the ones that are currently in the application
        Gallery gallery = galleryServices.getGalleryById(galleryId);
        List<Image> imagesLocal = imageServices.getImagesForGallery(gallery);

        // get remote images, the ones in the file system
        File directory = new File(galleryServices.getFsPathForGallery(gallery));
        File[] filesRemote = new File[0];
        if (directory.exists() && directory.isDirectory()) {
            filesRemote = directory.listFiles();
        }
        Map<String, GallerySyncDTO> result = new HashMap<String, GallerySyncDTO>();
        for (Image image : imagesLocal) {
            GallerySyncDTO syncElement = new GallerySyncDTO(image.getName());
            syncElement.setStatus(GallerySyncDTO.Status.MISSING_ON_REMOTE);
            syncElement.setLocal(image);
            syncElement.setRemote(null);

            result.put(image.getName(), syncElement);
        }

        for (File file : filesRemote) {

            String name = file.getName();

            GallerySyncDTO syncElement;

            if (result.containsKey(name)) {
                syncElement = result.get(name);
                syncElement.setStatus(GallerySyncDTO.Status.SYNCRONIZED);
            } else {
                syncElement = new GallerySyncDTO(name);
                syncElement.setStatus(GallerySyncDTO.Status.MISSING_ON_LOCAL);
                syncElement.setRemote(null);
            }

            Image image = new Image();
            image.setName(name);
            image.setSize(file.length());
            image.setContentType(new MimetypesFileTypeMap()
                    .getContentType(file));
            image.setUpdated(new Timestamp(file.lastModified()));
            syncElement.setRemote(image);
            result.put(image.getName(), syncElement);
        }

        if (logger.isDebugEnabled()) {
            logger.debug("synchronize(long) - end");
            logger.debug("return: " + result);
        }
        return new HashSet<GallerySyncDTO>(result.values());
    }

    
    public void syncronize(long galleryId, String[] deletes, String[] imports) {
        Gallery gallery = galleryServices.getGalleryById(galleryId);
                
        //get remote images, the ones in the file system
        File directory  = new File(galleryServices.getFsPathForGallery(gallery));
        
        for (String file : deletes) {
            deleteImage(galleryId, file);
        }
        
        for (String file : imports) {
            importImage(gallery, directory, file);
        }
        
    }

    private void importImage(Gallery gallery, File directory, String fileName) {
        File imageFile = new File(directory, fileName);
        String contentType = new MimetypesFileTypeMap().getContentType(imageFile);
        imageServices.add(imageFile, gallery, fileName, contentType);
    }

    private void deleteImage(long galleryId, String fileName) {
        imageServices.delete(galleryId, fileName);
    }   
}
